#include <stdlib.h>
#include <glut.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

GLfloat rotate;

// Zählervariable
int counter = 0;

// Vertice Struct
struct vertice
{
	float x,y,z;
}verticeA[500];

// Face Struct
struct face
{
	int a,b,c;
}faceA[500];


// File-Loader
void loadFile(char* filename)
{
	char line[255], comment[255];

	float x,y,z;
	FILE* file;
	int a,b,c;
	file = fopen(filename, "r");


	int i=1;
	int j=1;
	while(fgets(line, sizeof(line), file) != NULL)
	{
		if(sscanf(line, "#%s", comment))
		printf("valid: comment %s\n", comment);

		if (sscanf(line,"v %f %f %f", &x, &y, &z)) 
		{
			verticeA[i].x = x;
			verticeA[i].y = y; 
			verticeA[i].z = z;
			printf("Vertice x = %f \n\n", verticeA[i].x); 
			printf("Vertice y = %f \n\n", verticeA[i].y); 
			printf("Vertice z = %f \n\n", verticeA[i].z);
			i++;
		}

		if(sscanf(line,"f %i %i %i",&a,&b,&c))
		{
			faceA[j].a = a;
			faceA[j].b = b; 
			faceA[j].c = c;
			printf("Face a = %i \n\n", faceA[j].a); 
			printf("Face b = %i \n\n", faceA[j].b); 
			printf("Face c = %i \n\n", faceA[j].c);
			j++;
		}
	}
	counter = j;
	printf("Counter = %i \n\n", j);
}

// Initialisierungsmethode (Lichtquellen)
void init(void) 
{
   glClearColor(0.0, 0.0, 0.0, 0.0);
   glShadeModel(GL_SMOOTH);
   glEnable(GL_DEPTH_TEST);

   // Ein- und Ausschalten der Beleuchtung
   glEnable(GL_NORMALIZE);
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
   glEnable(GL_LIGHT1);
   glEnable(GL_LIGHT2);

   GLfloat ambient[] = {0.0, 0.0, 0.0, 1.0}; 

   // Lichtquelle 1 - Punktlichtquelle gerichtet
   GLfloat diffuseL1[] = {1.0, 0.0, 0.0, 1.0};              
   GLfloat specularL1[] = {1.0, 0.0, 1.0, 1.0};             
   GLfloat positionL1[] = {0.0, 10.0, 0.0, 0.0};

   glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
   glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuseL1);
   glLightfv(GL_LIGHT1, GL_SPECULAR, specularL1);
   glLightfv(GL_LIGHT1, GL_POSITION, positionL1);

   // Lichtquelle 2 - Spotlichtquelle
   GLfloat diffuseL2[] = {0.0, 1.0, 0.0, 1.0};              
   GLfloat specularL2[] = {0.0, 1.0, 1.0, 1.0};             
   GLfloat positionL2[] = {10.0, 0.0, 0.0, 1.0};
   GLfloat directionL2[] = {1, 0 ,0};
   GLfloat exponentL2[] = {120};
   GLfloat cutoffL2[] = {180};

   glLightfv(GL_LIGHT2, GL_AMBIENT, ambient);
   glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuseL2);
   glLightfv(GL_LIGHT2, GL_SPECULAR, specularL2);
   glLightfv(GL_LIGHT2, GL_POSITION, positionL2);
   glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, directionL2);
   glLightfv(GL_LIGHT2, GL_SPOT_EXPONENT, exponentL2);
   glLightfv(GL_LIGHT2, GL_SPOT_CUTOFF, cutoffL2);


   // Lichtquelle 3 - Punktlichtquelle ungerichtet
   GLfloat diffuseL3[] = {0.0, 0.0, 1.0, 1.0};              
   GLfloat specularL3[] = {1.0, 0.0, 1.0, 1.0};             
   GLfloat positionL3[] = {0.0, -10.0, 0.0, 1.0};

   glLightfv(GL_LIGHT3, GL_AMBIENT, ambient);
   glLightfv(GL_LIGHT3, GL_DIFFUSE, diffuseL3);
   glLightfv(GL_LIGHT3, GL_SPECULAR, specularL3);
   glLightfv(GL_LIGHT3, GL_POSITION, positionL3);

}

// Display Methode
void BruecknerTobiasDisplay(void)
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glEnable(GL_DEPTH_TEST);

   glLoadIdentity();
   gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
   glRotatef(rotate, 0.0, 1.0, 0.0);
   glPushMatrix();

   GLuint objModel = glGenLists(1);
   glNewList( objModel, GL_COMPILE );
   glBegin( GL_TRIANGLES );
   
   for(int i = 1; i < counter+1; i++)
   {
	   glVertex3f(verticeA[faceA[i].a].x,verticeA[faceA[i].a].y,verticeA[faceA[i].a].z);
	   glVertex3f(verticeA[faceA[i].b].x,verticeA[faceA[i].b].y,verticeA[faceA[i].b].z);
	   glVertex3f(verticeA[faceA[i].c].x,verticeA[faceA[i].c].y,verticeA[faceA[i].c].z);
   }

   glEnd();
   glEndList();
   glCallList(objModel);

   glFlush();
}

// Reshape Methode
void reshape(int w, int h)
{
   glViewport(0,0,(GLsizei)w,(GLsizei)h); 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
   glMatrixMode(GL_MODELVIEW);
}

// Keyboard Methode
void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         break;
   }
}

void idle(void)
{
	rotate+=0.01;
	glutPostRedisplay();
}


// Main Methode
int main(int argc, char** argv)
{
   loadFile("cube.obj");
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize(500, 500); 
   glutInitWindowPosition(100, 100);
   glutCreateWindow(argv[0]);  
   init();
   glutDisplayFunc(BruecknerTobiasDisplay);
   glutReshapeFunc(reshape);
   glutKeyboardFunc(keyboard);
   glutIdleFunc(idle);
   glutMainLoop();
   return 0;
}